<?php

/**
 * Description of exifInfo
 *
 * @author Martin Grossmann <snake.aas@gmail.com>
 * @version 1.0
 * @package Image
 *
 * @property-read $Maker Maker
 * @property-read $Model Model
 * @property-read $Orientation Orientation
 * @property-read $ExposureTime ExposureTime
 * @property-read $FNumber FNumber
 * @property-read $FocalLength FocalLength
 * @property-read $DateTime DateTime
 * @property-read $ISO ISO
 * @property-read $WhiteBalance WhiteBalance
 * @property-read $Flash Flash
 */
class exifInfo {

  const ORIENTATION_NORMAL          = 1;
  const ORIENTATION_FLIP_HORIZONTAL = 2;
  const ORIENTATION_180             = 3;
  const ORIENTATION_FLIP_VERTICAL   = 4;
  const ORIENTATION_TRANSPOSE       = 5;
  const ORIENTATION_270             = 6;
  const ORIENTATION_TRANSVERSE      = 7;
  const ORIENTATION_90              = 8;

  private $_inputExif;

  private $_exifArray;
  private $_textMode;
  
  public function __construct($fileName) {  
    $this->_exifArray = array();  
    $this->_textMode = false;
    
    $this->_inputExif = @read_exif_data($fileName);
    $this->decodeExif();
  }

  
  private function decodeExif() {
    $this->_exifArray['Model']        = $this->_getModel();
    $this->_exifArray['Maker']        = $this->_getMaker();
    $this->_exifArray['DateTime']     = $this->_getDateTime();
    $this->_exifArray['ExposureTime'] = $this->_getExposureTime();
    $this->_exifArray['FNumber']      = $this->_getFNumber();
    $this->_exifArray['Flash']        = ($this->_textMode) ? self::FlashCodeToText($this->_getFlash()) : $this->_getFlash();
    $this->_exifArray['FocalLength']  = $this->_getFocalLength();
    $this->_exifArray['ISO']          = $this->_getISO();
    $this->_exifArray['WhiteBalance'] = ($this->_textMode) ? self::WBCodeToText($this->_getWB()) : $this->_getWB();    
  }

  public function setTextMode() {
    $this->_textMode = true;
    $this->decodeExif();
  }
  
  public function setNonTextMode() {
    $this->_textMode = false;
    $this->decodeExif();
  }
  
  public function getAsArray() {
    return $this->_exifArray;
  }
  
  public static function WBCodeToText($code) {
    switch($code) {
      case 0: return T_('Auto'); break;
      case 1: return T_('Manual'); break;
      default: return T_('Unknown');
    }
  }

  public static function FlashCodeToText($code) {
    switch($code) {
      case 0x0	: return T_('No Flash');                                            break;
      case 0x1	: return T_('Fired');                                               break;
      case 0x5	: return T_('Fired, Return not detected');                          break;
      case 0x7	: return T_('Fired, Return detected');                              break;
      case 0x8	: return T_('On, Did not fire');                                    break;
      case 0x9	: return T_('On, Fired');                                           break;
      case 0xd	: return T_('On, Return not detected');                             break;
      case 0xf  : return T_('On, Return detected');                                 break;
      case 0x10 : return T_('Off, Did not fire');                                   break;
      case 0x14	: return T_('Off, Did not fire, Return not detected');              break;
      case 0x18	: return T_('Auto, Did not fire');                                  break;
      case 0x19	: return T_('Auto, Fired');                                         break;
      case 0x1d	: return T_('Auto, Fired, Return not detected');                    break;
      case 0x1f	: return T_('Auto, Fired, Return detected');                        break;
      case 0x20	: return T_('No flash function');                                   break;
      case 0x30	: return T_('Off, No flash function');                              break;
      case 0x41	: return T_('Fired, Red-eye reduction');                            break;
      case 0x45	: return T_('Fired, Red-eye reduction, Return not detected');       break;
      case 0x47	: return T_('Fired, Red-eye reduction, Return detected');           break;
      case 0x49	: return T_('On, Red-eye reduction');                               break;
      case 0x4d	: return T_('On, Red-eye reduction, Return not detected');          break;
      case 0x4f	: return T_('On, Red-eye reduction, Return detected');              break;
      case 0x50	: return T_('Off, Red-eye reduction');                              break;
      case 0x58	: return T_('Auto, Did not fire, Red-eye reduction');               break;
      case 0x59	: return T_('Auto, Fired, Red-eye reduction');                      break;
      case 0x5d	: return T_('Auto, Fired, Red-eye reduction, Return not detected'); break;
      case 0x5f	: return T_('Auto, Fired, Red-eye reduction, Return detected');     break;
      default   : return T_('Unknown');
    }
  }
  
  public static function ValueToText($name, $value) {
    switch ($name) {
      case 'Flash':
        return self::FlashCodeToText($value);
        break;
      case 'WhiteBalance':
        return self::WBCodeToText($value);
        break;
      default:
        return $value;
        break;
    }
  }
  
  public static function ParamToText($Parameter) {
    switch ($Parameter) {
      case 'Maker':
        return T_('Maker');
        break;
      case 'Model':
        return T_('Model');
        break;
      case 'DateTime':
        return T_('Time Taken Photo');
        break;
      case 'ExposureTime':
        return T_('Exposure Time');
        break;
      case 'FNumber':
        return T_('FNumber');
        break;
      case 'Flash':
        return T_('Flash');
        break;
      case 'FocalLength':
        return T_('Focal Length');
        break;
      case 'ISO':
        return T_('ISO');
        break;
      case 'WhiteBalance':
        return T_('White Balance');
        break;
      default:
        return $Parameter;
        break;
    }
  }

  private function _getMaker() {
    return isset($this->_inputExif['Make']) ? $this->_inputExif['Make'] : null;
  }
  
  private function _getModel() {
    return isset($this->_inputExif['Model']) ? $this->_inputExif['Model'] : null;
  }
  
  private function _getExposureTime() {
    if (isset($this->_inputExif['ExposureTime'])) {
      list($d1, $d2) = explode('/',$this->_inputExif['ExposureTime']);
      if ($d1 > 0 && $d2 > 0)
        $e = $d1 / $d2;
      else
        $e = $this->_inputExif['ExposureTime'];

      if ($e < 1 && $e > 0)
          $e="1/" . round(1 / $e, 0);
      else
          $e=round($e,1) ;

      return $e;
    } else
      return null;
  }
  
  private function _getFNumber() {
    return isset($this->_inputExif['COMPUTED']['ApertureFNumber']) ? $this->_inputExif['COMPUTED']['ApertureFNumber'] : null;
  }
  
  private function _getFocalLength() {
    if (isset($this->_inputExif['FocalLength'])) {
      list($d1, $d2) = explode('/',$this->_inputExif['FocalLength']);
      return round($d1 / $d2, 1);
    } else
      return null;
  }
  
  private function _getDateTime() {
    global $config;
    $date = null;

    if (isset($this->_inputExif['DateTimeOriginal']))
      $date = $this->_inputExif['DateTimeOriginal'];

    if (empty($date) && isset($this->_inputExif['DateTime']))
      $date = $this->_inputExif['DateTime'];

         
    return ($date === null) ? null : DateTime::createFromFormat('Y:m:d H:i:s', $date)->format($config['Page']['DateFormat']);
  }
  
  private function _getISO() {
    $iso = null;
    if (isset($this->_inputExif['ISOSpeedRatings']))
      $iso = $this->_inputExif['ISOSpeedRatings'];
    else if (isset($this->_inputExif['MakerNote']) && isset($this->_inputExif['ModeArray'])) {
        // Add ISO for PowerShot cameras
      switch (@$this->_inputExif['ModeArray'][16]) {
        case 15: $iso="auto";break;
        case 16: $iso="50";break;
        case 17: $iso="100";break;
        case 18: $iso="200";break;
        case 19: $iso="400";break;
      }
    }
    return $iso;
  }
  
  private function _getWB() {
    return isset($this->_inputExif['WhiteBalance']) ? $this->_inputExif['WhiteBalance'] : null;
  }

  private function _getFlash() {
    return isset($this->_inputExif['Flash']) ? $this->_inputExif['Flash'] : null;
  }

  public function __get($name) {

    if($name = 'Orientation') 
      return isset($this->_inputExif['Orientation']) ? $this->_inputExif['Orientation'] : 1;
    
    if(array_key_exists($name, $this->_exifArray)) {
      return $this->_exifArray[$name];
    } else {
      throw new Exception(T_("Trying to get undefined property")." ".$name);
    }
    /*switch($name) {

      case 'Maker':
        return ;
        break;

      case 'Model':
        return ;
        break;

      case 'Orientation':
        
        break;

      case 'ExposureTime':
        return ;
        break;

      case 'FNumber':
        return ;
        break;

      case 'FocalLength':
        return ;
        break;

      case 'DateTime':
        return ;        
        break;

      case 'ISO':
        return ;
        break;

      case 'WhiteBalance':
        return ;
        break;

      case 'Flash':
        return ;
        break;
    }*/
  }

  public function __set($name, $value) {
    switch ($name) {
      case 'Orientation':
        $this->_inputExif['Orientation'] = $value;
        break;
    }
  }

}
?>
